/**	\file
 *	\brief Common types for all the programs.
 */

#ifndef MDS_TYPES_INCLUDED
#define MDS_TYPES_INCLUDED 1

#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
#include <float.h>

#if defined(MDS_DOUBLE) && MDS_DOUBLE == 1
typedef double Real;
#define MDS_F(X) X
#define REAL_EPSILON DBL_EPSILON
#else
typedef float  Real;
#define MDS_F(X) X##f
#define REAL_EPSILON FLT_EPSILON
#endif

/*******************************************************************************
 *	Memory
 ******************************************************************************/

/** \brief Counter of allocated/freed bytes
 *	Global variable used by mds_calloc and mds_free.
 */
extern uint64_t mds_bytes; 

/** \brief Replacement for calloc. 
 *
 *	Calls calloc(count,size) and update mds_bytes upon success.
 *
 *	\param count the number of items.
 *	\param size  the size of one item.
 *	\return NULL upon failure, an array of count*size bytes upon success.
 */
void * mds_calloc(size_t count, size_t size);

/** \brief Replacement for free.
 *	
 *	Calls free(p) and update mds_bytes accordingly.
 *	\param p     the previously allocated array, may be NULL.
 *	\param count the previously allocated number of items.
 *	\param size  the size of one item > 0
 */
void   mds_free(void *p, size_t count, size_t size);


#if !defined(NDEBUG)
/* Checked Alloc/Free */
#	define MDS_CALLOC_AS(TYPE,N) (TYPE *)mds_calloc(N,sizeof(TYPE))
#	define MDS_FREE_AS(TYPE,p,N)         mds_free(p,N,sizeof(TYPE))
#	define MDS_MEMORY()          fprintf( stderr, "[mds_bytes] <%llu>\n", (unsigned long long) mds_bytes)
#else
/* NDEBUG Alloc/Free */
#	define MDS_CALLOC_AS(TYPE,N) (TYPE *)calloc(N,sizeof(TYPE))
#	define MDS_FREE_AS(TYPE,p,N)         free(p)
#	define MDS_MEMORY()
#endif



/*******************************************************************************
 *	Error
 ******************************************************************************/

#if defined(__GNUC__)
#	define	MDS_LIKE_PRINTF(i,j) __attribute__ ((format (printf, i, j)))
#else
#	define	MDS_LIKE_PRINTF(i,j)
#endif

/** \brief Formatted error logging.
 *	
 *	printf-like function that outputs the error string
 *	associated with the last errno, then the formatted message.
 *	\param fp    the logging file, must be valid.
 *	\param when  the more detailed format string. 
 */
void         mds_perror( FILE *fp, const char *when,...) MDS_LIKE_PRINTF(2,3);

long         mds_file_length( FILE *fp );

/** \brief 3D vector of indices.
 *
 */
typedef struct 
{
	size_t x,y,z;
}
mds_uvector;



#endif /* MDS_TYPES_INCLUDED */
